%% 对话 92: 最终混合优化算法脚本 (稳定函数名版)
%
% 主程序文件 (main.m)
% V2 更新: 增加了在脚本末尾自动保存最终优化结果的功能。
%
clear; clc; close all;
%% ========================================================================
% 设置区: 在这里调整算法参数
% ========================================================================
% --- 阶段一: 广域探索参数 ---
options1.iterations = 50;
options1.batch_size = 100;
options1.patience = 10; 
% --- 阶段二: 深度优化参数 ---
p = gcp('nocreate');
if isempty(p), num_cores = 1; else, num_cores = p.NumWorkers; end
options2.max_passes = 5; 
options2.time_limit_minutes = 10; 
% 以下为阶段二优化器内部使用的参数
options2.num_focus_nodes_multiplier = 1; % 焦点节点数量 = 此值 * CPU核心数
options2.batch_size_multiplier = 10; % 批次大小 = 此值 * CPU核心数
% ========================================================================
%% 第一、二部分：加载数据与预处理
disp('--- Section 1&2: Loading and pre-processing data ---');
try
    nodes_table = readtable('Conv_Case0_Nodes.csv');
    edges_table = readtable('Conv_Case0_Edges.csv');
catch ME
    disp('错误：无法加载CSV文件。'); rethrow(ME);
end
% ... (省略与之前版本相同的预处理代码) ...
nodes_table.OpCode = double(categorical(nodes_table.Op));
nodes_table.TypeCode = double(categorical(nodes_table.Type));
categories_op = categories(categorical(nodes_table.Op));
categories_type = categories(categorical(nodes_table.Type));
code_map.op.ALLOC = find(strcmp('ALLOC', categories_op), 1);
code_map.op.FREE = find(strcmp('FREE', categories_op), 1);
code_map.type.L1 = find(strcmp('L1', categories_type), 1);
code_map.type.UB = find(strcmp('UB', categories_type), 1);
code_map.type.L0A = find(strcmp('L0A', categories_type), 1);
code_map.type.L0B = find(strcmp('L0B', categories_type), 1);
code_map.type.L0C = find(strcmp('L0C', categories_type), 1);
G = digraph(edges_table.StartNodeId + 1, edges_table.EndNodeId + 1, [], nodes_table);
disp('数据加载与预处理完成。');
%% 第三部分：生成初始可行解与预计算
disp('--- Section 3: Generating initial solution and pre-computation ---');
initial_schedule = generate_l0_constrained_schedule(G, code_map);
[initial_score, initial_history] = calculate_max_vstay(initial_schedule, G, code_map);
fprintf('初始可行解的峰值内存占用为: %d\n', initial_score);
disp('正在预计算节点间的依赖关系...');
is_ancestor = full(adjacency(transclosure(G)));
disp('依赖关系预计算完成。');
%% 第四部分：执行两阶段混合优化
disp('--- Section 4: Executing the two-phase hybrid optimization ---');
fprintf('\n--- 开始阶段一: 广域探索 ---\n');
[schedule_phase1, score_phase1] = optimizer_random_sampling_bottleneck(initial_schedule, initial_history, initial_score, G, code_map, is_ancestor, options1);
fprintf('--- 阶段一完成! 分数从 %d 优化至 %d ---\n', initial_score, score_phase1);
%%
fprintf('\n--- 开始阶段二: 深度优化 (最终版逻辑) ---\n');
[~, history_phase1] = calculate_max_vstay(schedule_phase1, G, code_map);
% ---【核心修改】--- 调用稳定不变的函数名
[final_schedule, final_score] = optimizer_systematic_search_bottleneck(schedule_phase1, history_phase1, score_phase1, G, code_map, is_ancestor, options2);
fprintf('--- 阶段二完成! 分数从 %d 进一步优化至 %d ---\n', score_phase1, final_score);
%% 第五部分：最终结果总结与（基础）可视化
disp('--- Section 5: Final results and visualization ---');
% ... (省略与之前版本相同的总结与可视化代码) ...
[~, history_phase1_final] = calculate_max_vstay(schedule_phase1, G, code_map);
[~, final_history] = calculate_max_vstay(final_schedule, G, code_map);
fprintf('\n\n--- 最终优化结果总结 ---\n');
fprintf('初始解分数: %d\n', initial_score);
fprintf('阶段一后分数: %d\n', score_phase1);
fprintf('最终优化分数: %d\n', final_score);
if initial_score > 0
    fprintf('总计内存占用降低了: %d (%.2f%%)\n', initial_score - final_score, ...
            100 * (initial_score - final_score) / initial_score);
end
figure('Name', '三阶段V_stay对比图');
plot(initial_history, 'r:', 'LineWidth', 1.5, 'DisplayName', sprintf('初始解 (max V_{stay} = %d)', initial_score));
hold on;
plot(history_phase1_final, 'g--', 'LineWidth', 1.5, 'DisplayName', sprintf('阶段一优化解 (max V_{stay} = %d)', score_phase1));
plot(final_history, 'b-', 'LineWidth', 2, 'DisplayName', sprintf('最终优化解 (max V_{stay} = %d)', final_score));
title('优化过程各阶段缓存占用(V_{stay})对比');
xlabel('执行步骤'); ylabel('L1+UB 缓存占用量');
legend('Location', 'best'); grid on; hold off;

%% 第六部分：高级可视化分析
disp('--- Section 6: Generating advanced visualizations ---');
num_nodes = numnodes(G);

% --- 可视化 1: 调度方案对比图 (甘特图风格) ---
figure('Name', '调度方案对比图');
% 计算每个节点在初始和最终方案中的位置
initial_pos = zeros(num_nodes, 1);
initial_pos(initial_schedule) = 1:length(initial_schedule);
final_pos = zeros(num_nodes, 1);
final_pos(final_schedule) = 1:length(final_schedule);
% 绘制节点位置
hold on;
plot(initial_pos, 1:num_nodes, 'ro', 'MarkerSize', 8, 'DisplayName', '初始位置');
plot(final_pos, 1:num_nodes, 'bx', 'MarkerSize', 8, 'LineWidth', 1.5, 'DisplayName', '最终位置');
% 为移动过的节点绘制连线
for i = 1:num_nodes
    if initial_pos(i) ~= final_pos(i)
        line([initial_pos(i), final_pos(i)], [i, i], 'Color', [0.5 0.5 0.5], 'LineStyle', ':', 'HandleVisibility', 'off');
    end
end
hold off;
% 美化图表
title('初始方案与最终方案节点位置对比');
xlabel('执行步骤');
ylabel('节点 ID');
legend('Location', 'best');
set(gca, 'YDir', 'reverse'); % 将节点ID 1放在顶部
grid on;

% --- 可视化 2: 节点移动距离直方图 ---
figure('Name', '节点移动距离直方图');
displacement = final_pos - initial_pos; % 计算每个节点的位置变化
histogram(displacement);
title('节点在优化过程中的移动距离分布');
xlabel('位置变化量 (最终位置 - 初始位置)');
ylabel('节点数量');
grid on;

% --- 可视化 3: 内存瓶颈剖析图 (增强版V_stay对比图) ---
figure('Name', '内存瓶颈剖析图');
hold on;
% 绘制三条内存历史曲线
plot(initial_history, 'r:', 'LineWidth', 1.5, 'DisplayName', sprintf('初始解 (max V_{stay} = %d)', initial_score));
plot(history_phase1_final, 'g--', 'LineWidth', 1.5, 'DisplayName', sprintf('阶段一优化解 (max V_{stay} = %d)', score_phase1));
plot(final_history, 'b-', 'LineWidth', 2, 'DisplayName', sprintf('最终优化解 (max V_{stay} = %d)', final_score));
% 找出最终方案的瓶颈
[peak_val, peak_idx] = max(final_history);
culprit_node_id = final_schedule(peak_idx);
% 在图上标记瓶颈
xline(peak_idx, 'm--', 'LineWidth', 1.5, 'DisplayName', sprintf('最终方案瓶颈 (步骤 %d)', peak_idx), 'LabelOrientation', 'horizontal');
text_str = sprintf('<- 瓶颈节点: %d\n    内存: %d', culprit_node_id, peak_val);
text(peak_idx + 0.01*length(final_history), peak_val, text_str, 'HorizontalAlignment', 'left', 'VerticalAlignment', 'top', 'FontSize', 9, 'Color', 'm');
hold off;
% 美化图表
title('增强版 V_{stay} 对比与最终方案瓶颈分析');
xlabel('执行步骤');
ylabel('L1+UB 缓存占用量');
legend('Location', 'best');
grid on;

%% 第七部分：保存最终结果
disp('--- Section 7: Saving final results ---');
output_filename = 'final_schedule_optimized.txt';
% 将1-based的MATLAB索引转换回0-based的节点ID进行保存
schedule_to_save = final_schedule - 1; 
try
    writematrix(schedule_to_save, output_filename);
    fprintf('最终优化方案已成功保存至: %s\n', output_filename);
catch ME
    fprintf('错误：无法保存最终方案到文件 "%s"。\n', output_filename);
    rethrow(ME);
end

disp('--- 所有分析与可视化完成 ---');